package winOrDie.Net;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Vector;

/**
 * This public class provides WoD_TCP_Channel
 *
 */
public class WoD_TCP_Channel 
implements Runnable
{

	/**
	 * Internal variable to stop this thread.
	 */
	private boolean fIsStopRequested = false;


	private Socket socket = null;
	private InputStream inputStream = null;
	private DataInputStream dataInputStream = null;
	private OutputStream outputStream = null;
	private DataOutputStream dataOutputStream = null;
	
	Vector<WoD_TCP_Channel_Listener> listeners = null;
	
	private Thread thread_WoD_TCP_Channel = null;
	
	public synchronized void add_WoD_TCP_Channel_Listener(WoD_TCP_Channel_Listener listener)
	{
		listeners.add(listener);
	}
	
	public synchronized void remove_WoD_TCP_Channel_Listener(WoD_TCP_Channel_Listener listener)
	{
		listeners.remove(listener);
	}
	
	protected void fire_WoD_TCP_Channel_Event(WoD_TCP_Channel_Event event)
	{
		for (WoD_TCP_Channel_Listener listener : listeners) {
			listener.on_WoD_TCP_Channel_Change(event);
		}
	}
	
	public WoD_TCP_Channel(Socket socket) throws Exception 
	{
		this.socket = socket;
		
		try {
			inputStream = this.socket.getInputStream();
			outputStream = this.socket.getOutputStream();
		} catch (Exception e) {
			Exception exception = new Exception("Error on socket inputStream. " + e.getMessage());
			throw exception;
		}
		dataInputStream = new DataInputStream(inputStream);
		dataOutputStream = new DataOutputStream(outputStream);
		
		listeners = new Vector<WoD_TCP_Channel_Listener>();
	}
	
	@Override
	public void run() {
		String message_UTF = new String();
		while (!fIsStopRequested) {
			try {
				message_UTF = dataInputStream.readUTF();
				
				/*
				 * Send message to all listeners
				 */
				WoD_TCP_Channel_Event event = new WoD_TCP_Channel_Event(this);
				event.setEvent_Type(WoD_TCP_Channel_Event.MESSAGE_RECEIVED);
				event.setData(message_UTF);
				fire_WoD_TCP_Channel_Event(event);
				
			} catch (IOException e) {
				/*
				 * Send error to all listeners and stop thread 
				 */
				WoD_TCP_Channel_Event event = new WoD_TCP_Channel_Event(this);
				event.setEvent_Type(WoD_TCP_Channel_Event.ERROR);
				String message = "Error on tcp channel. " + e.getMessage();
				event.setData(message);
				fire_WoD_TCP_Channel_Event(event);
				fIsStopRequested = true;
			}
		}
		
	}
	
	
	public void start_WoD_TCP_Channel()
	{
		thread_WoD_TCP_Channel = new Thread(this);
		thread_WoD_TCP_Channel.setDaemon(true);
		thread_WoD_TCP_Channel.start();
	}
	
	public synchronized void sendData(String message) throws Exception
	{
		try {
			dataOutputStream.writeUTF(message);
		} catch (IOException e) {
			Exception exception = new Exception("Error sending data. " + e.getMessage());
			throw exception;
		}
	}
	
}
